package com.guchenbo.example.thread.singleton;

import java.util.concurrent.CountDownLatch;

/**
 * @Author guchenbo
 * @Date 2019/7/5.
 */
public class MainTest {
    private static CountDownLatch latch = new CountDownLatch(1);

    public static void main(String[] args) {
        MainTest test = new MainTest();
//                test.noSingleton();
//                test.unsafeSingleton();
//        test.syncSingleton();
        test.unsafeDoubleCheckSingleton();
//        test.doubleCheckSingleton();
//        test.singletonHolder();
    }

    public void noSingleton() {
        System.out.println("###########noSingleton#############");
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    latch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Singleton instance = NoSingletonFactory.getInstance();
                System.out.println(instance);
            }).start();
        }
        latch.countDown();
    }

    public void unsafeSingleton() {
        System.out.println("###########unsafeSingleton#############");
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    latch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Singleton instance = UnsafeSingletonFactory.getInstance();
                System.out.println(instance);
            }).start();
        }
        latch.countDown();
    }

    public void syncSingleton() {
        System.out.println("###########syncSingleton#############");
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    latch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Singleton instance = SyncSingletonFactory.getInstance();
                System.out.println(instance);
            }).start();
        }
        latch.countDown();
    }

    public void unsafeDoubleCheckSingleton() {
        System.out.println("###########unsafeDoubleCheckSingleton#############");
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                try {
                    latch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Singleton instance = UnsafeDoubleCheckSingletonFactory.getInstance();
                System.out.println(instance.getName().trim());
            }).start();
        }
        latch.countDown();
    }

    public void doubleCheckSingleton() {
        System.out.println("###########doubleCheckSingleton#############");
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                try {
                    latch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Singleton instance = DoubleCheckSingletonFactory.getInstance();
                System.out.println(instance);
            }).start();
        }
        latch.countDown();
    }


    public void singletonHolder() {
        System.out.println("###########singletonHolder#############");
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                try {
                    latch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Singleton instance = SingletonHolderFactory.getInstance();
                System.out.println(instance);
            }).start();
        }
        latch.countDown();
    }
}
